// 认证中间件
import { Request, Response, NextFunction } from 'express'
import { JWTManager } from '../lib/jwt'
import { CacheManager } from '../lib/memory-cache'
import { prisma } from '../lib/prisma'

// 扩展Request接口
declare global {
  namespace Express {
    interface Request {
      user?: {
        id: string
        email: string
      }
    }
  }
}

// 认证中间件
export const authenticate = async (req: Request, res: Response, next: NextFunction) => {
  try {
    const authHeader = req.headers.authorization
    
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return res.status(401).json({
        error: '未提供认证令牌'
      })
    }

    const token = authHeader.substring(7) // 移除 'Bearer ' 前缀
    
    // 验证访问令牌
    const payload = JWTManager.verifyAccessToken(token)
    if (!payload) {
      return res.status(401).json({
        error: '无效的认证令牌'
      })
    }

    // 检查用户是否存在（使用缓存优化）
    const cacheKey = CacheManager.getUserCacheKey(payload.userId, 'info')
    let user = await CacheManager.get(cacheKey)
    
    if (!user) {
      user = await prisma.user.findUnique({
        where: { id: payload.userId },
        select: {
          id: true,
          email: true,
          emailVerified: true
        }
      })
      
      if (!user) {
        return res.status(401).json({
          error: '用户不存在'
        })
      }
      
      // 缓存用户信息（5分钟）
      await CacheManager.set(cacheKey, user, 300)
    }

    // 将用户信息添加到请求对象
    req.user = {
      id: (user as any).id,
      email: (user as any).email
    }

    next()
  } catch (error) {
    console.error('认证中间件错误:', error)
    res.status(500).json({
      error: '认证服务异常'
    })
  }
}

// 可选认证中间件（用户可能已登录也可能未登录）
export const optionalAuthenticate = async (req: Request, res: Response, next: NextFunction) => {
  try {
    const authHeader = req.headers.authorization
    
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return next() // 没有令牌，继续执行
    }

    const token = authHeader.substring(7)
    const payload = JWTManager.verifyAccessToken(token)
    
    if (payload) {
      // 检查用户是否存在
      const cacheKey = CacheManager.getUserCacheKey(payload.userId, 'info')
      let user = await CacheManager.get(cacheKey)
      
      if (!user) {
        user = await prisma.user.findUnique({
          where: { id: payload.userId },
          select: {
            id: true,
            email: true,
            emailVerified: true
          }
        })
        
        if (user) {
          await CacheManager.set(cacheKey, user, 300)
        }
      }
      
      if (user) {
        req.user = {
          id: (user as any).id,
          email: (user as any).email
        }
      }
    }

    next()
  } catch (error) {
    console.error('可选认证中间件错误:', error)
    next() // 出错时继续执行，不阻断请求
  }
}

// 邮箱验证检查中间件
export const requireEmailVerified = async (req: Request, res: Response, next: NextFunction) => {
  try {
    if (!req.user) {
      return res.status(401).json({
        error: '需要登录'
      })
    }

    const user = await prisma.user.findUnique({
      where: { id: req.user.id },
      select: { emailVerified: true }
    })

    if (!user || !user.emailVerified) {
      return res.status(403).json({
        error: '需要验证邮箱后才能访问此功能'
      })
    }

    next()
  } catch (error) {
    console.error('邮箱验证检查错误:', error)
    res.status(500).json({
      error: '验证服务异常'
    })
  }
}

// 管理员权限检查中间件（如果需要）
export const requireAdmin = async (req: Request, res: Response, next: NextFunction) => {
  try {
    if (!req.user) {
      return res.status(401).json({
        error: '需要登录'
      })
    }

    // 这里可以添加管理员权限检查逻辑
    // 例如检查用户角色或特定权限
    
    next()
  } catch (error) {
    console.error('管理员权限检查错误:', error)
    res.status(500).json({
      error: '权限验证异常'
    })
  }
}

// 令牌刷新中间件
export const refreshTokenIfNeeded = async (req: Request, res: Response, next: NextFunction) => {
  try {
    const authHeader = req.headers.authorization
    
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return next()
    }

    const token = authHeader.substring(7)
    
    // 检查令牌是否即将过期
    if (JWTManager.isTokenExpiringSoon(token)) {
      const payload = JWTManager.verifyAccessToken(token)
      if (payload) {
        // 生成新的访问令牌
        const newAccessToken = JWTManager.generateAccessToken({
          userId: payload.userId,
          email: payload.email
        })
        
        // 在响应头中返回新令牌
        res.setHeader('X-New-Access-Token', newAccessToken)
      }
    }

    next()
  } catch (error) {
    console.error('令牌刷新中间件错误:', error)
    next() // 出错时继续执行
  }
}